﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Input;
 using Microsoft.Xna.Framework.Media;

namespace mightyParticles
{
    class ParticleEngine
    {
        public List<CParticle> particleList = new List<CParticle>();
        public Random random = new Random();
        public GameTime nowT = new GameTime();
        public Vector2 position; public float size; public int numOfParticles; public float time;
        public float alpha; int count;

        public void UpdateParticles(GameTime gameTime)
        {
            float now = (float)nowT.TotalGameTime.TotalMilliseconds;
            for(int i = particleList.Count-1;i >= 0; i--)
            {
                CParticle part = particleList[i];
                float timeAlive = now - part.birthTime;

                if(timeAlive > part.maxAge)
                    particleList.RemoveAt(i);

                else
                {
                    float relAge = timeAlive / part.maxAge;
                    part.position += part.direction;


                    part.color = new Color(new Vector4(1, 1, 1, 2));

                    Vector2 positionFromCenter = part.position - part.originalPosition;
                    float distance = positionFromCenter.Length();
                    if (distance > 100)
                        particleList[i].position = particleList[i].originalPosition;
                    part.scaling = (50.0f + distance) / 200.0f;

                    particleList[i] = part;
                }
            }
        }
        public void AddExplosion(Vector2 explosionPosition, int numberOfParticles, float size, float maxAge, GameTime gameTime)
        {
            for(int i = 0;i < numberOfParticles; i++)
                AddExplosionParticle(explosionPosition, size, maxAge, gameTime);
        }
        public void AddExplosionParticle(Vector2 explosionPos, float explosionSize, float maxAge, GameTime gameTime)
        {
            CParticle part = new CParticle();
            part.originalPosition = explosionPos;
            part.position = part.originalPosition;

            part.birthTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
            part.maxAge = maxAge;
            part.scaling = 0.25f;
            part.color = Color.White;

            float particleDistance = (float)random.NextDouble()*explosionSize;
            Vector2 displacement = new Vector2(particleDistance,0);
            float angle = MathHelper.ToRadians(random.Next(360));
            displacement = Vector2.Transform(displacement, Matrix.CreateRotationZ(angle));

            part.direction = displacement;
            part.acceleration = -part.direction;

            particleList.Add(part);
        }
        public void DrawExplosion(SpriteBatch spriteBatch, Texture2D explosionTexture)
        {
            for (int i = 0; i < particleList.Count; i++)
            {
                CParticle part = particleList[i];
                spriteBatch.Draw(explosionTexture, part.position, null, part.color, i, new Vector2(16, 16), part.scaling, SpriteEffects.None, 1);
            }
        }
        public ParticleEngine()
        {
            time = (float)nowT.TotalGameTime.TotalMilliseconds;
            count = 0;
        }
        /// <summary>
        /// Constructor for O-Ring
        /// </summary>
        /// <param name="vposition"></param>
        /// <param name="fsize"></param>
        /// <param name="nNumOfParticles"></param>
        /// <param name="ftime"></param>
        public ParticleEngine(Vector2 vposition, float fsize, int nNumOfParticles, float ftime)
        {
            position = vposition; size = fsize; numOfParticles = nNumOfParticles; time = ftime;

            for (int i = 0; i < numOfParticles; i++)
            {
                CParticle particle = new CParticle();
                particle.originalPosition = position;
                particle.position = position;
                particle.birthTime = (float)nowT.TotalGameTime.TotalMilliseconds;
                particle.maxAge = time;
                particle.scaling = 1.0f;
                particle.color = Color.CornflowerBlue;

                float rad = MathHelper.ToRadians((float)i);

                particle.direction.X = 3.0f * (float)Math.Cos(i);
                particle.direction.Y = 3.0f * (float)Math.Sin(i);
                //particle.acceleration = -particle.direction;

                particleList.Add(particle);
            }
        }
        public void DrawORing(SpriteBatch spriteBatch, Texture2D texture)
        {
            //update particles
            for (int i = particleList.Count - 1; i >= 0; i--)
            {
                particleList[i].position += particleList[i].direction;
                particleList[i].direction += particleList[i].acceleration;
                Vector2 positionFromCenter = particleList[i].position - particleList[i].originalPosition;
                float distance = positionFromCenter.Length();
                if (distance > size)
                    particleList[i].position = particleList[i].originalPosition;
                
                CParticle part = particleList[i];
                spriteBatch.Draw(texture, part.position, null, part.color, i, new Vector2(16, 16), part.scaling, SpriteEffects.None, 1);
            }
            
        }
        public ParticleEngine(Vector2 vposition, int nNumOfParticles, float fsize)
        {
            position = vposition; numOfParticles = nNumOfParticles; size = fsize;

            for (int i = 0; i < numOfParticles; i++)
            {
                CParticle particle = new CParticle();
                particle.originalPosition = position;
                particle.position = position;
                particle.birthTime = (float)nowT.TotalGameTime.TotalMilliseconds;
                particle.scaling = 1.0f;
                particle.color = Color.OrangeRed;

                float particleDistance = (float)random.NextDouble() * size;
                Vector2 displacement = new Vector2(particleDistance, 0);
                float angle = MathHelper.ToRadians(random.Next(360));
                displacement = Vector2.Transform(displacement, Matrix.CreateRotationZ(angle));

                if ((i % 2) == 0)
                    particle.direction = displacement*0.05f;
                else
                    particle.direction = -displacement*0.05f;
                particle.direction.Y = -20.0f;
                particle.acceleration.X = 0.0f;
                particle.acceleration.Y = 0.75f;

                particleList.Add(particle);
            }
        }
        public void DrawSparks(SpriteBatch spriteBatch, Texture2D texture,Vector2 pos)
        {
            for (int i = particleList.Count - 1; i >= 0; i--)
            {
                particleList[i].originalPosition = pos;
                particleList[i].position += particleList[i].direction;
                particleList[i].direction += particleList[i].acceleration;
                Vector2 positionFromCenter = particleList[i].position - particleList[i].originalPosition;
                float distance = positionFromCenter.Length();
                if (distance > size)
                {
                    particleList[i].position = particleList[i].originalPosition;
                    particleList[i].direction.Y = -20.0f;
                }

                CParticle part = particleList[i];
                spriteBatch.Draw(texture, part.position, null, part.color, i, new Vector2(16, 16), part.scaling, SpriteEffects.None, 1);
            }
        }
        public void Trail(SpriteBatch spriteBatch, Texture2D texture, Vector2 pos, int numParticles, float age, GameTime gameTime)
        {
            CParticle particle = new CParticle();
            time = (float)gameTime.TotalGameTime.TotalMilliseconds;
            if (count == 0)
            {
                particle = new CParticle();
                particle.originalPosition = pos;
                particle.position = pos;
                particle.birthTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
                particle.maxAge = age;
                particle.scaling = 1.0f;
                particle.color = Color.BlueViolet;
                particleList.Add(particle);
                count++;
            }
            for (int i = 1; i < numParticles; i++)
            {
                if (time - particle.birthTime > age)
                {
                    particle = new CParticle();
                    particle.originalPosition = pos;
                    particle.position = pos;
                    particle.birthTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
                    particle.maxAge = age;
                    particle.scaling = 1.0f;
                    particle.color = Color.BlueViolet;
                    particleList.Add(particle);
                }
            }
            for (int i = particleList.Count - 1; i >= 0; i--)
            {
                if (time - particleList[i].birthTime < 1000)
                {
                    spriteBatch.Draw(texture, particleList[i].position, null, particleList[i].color, i, new Vector2(16, 16), particleList[i].scaling, SpriteEffects.None, 1);
                    
                }
                if (time - particle.birthTime > 1000)
                    particleList.Remove(particleList[i]);
            }
        }
        public void Pulse(SpriteBatch spriteBatch, Texture2D texture, Vector2 pos, float length, float velocity)
        {
            if (count == 0)
            {
                for (int i = 0; i < 50; i++)
                {
                    CParticle part = new CParticle();
                    part.originalPosition = pos;
                    part.position = pos;
                    part.color = Color.BlueViolet;
                    part.scaling = 2.0f;
                    particleList.Add(part);
                }
                for (int i = 0; i < (pos.X+length)-pos.X; i++)
                {
                    CParticle particle = new CParticle();
                    particle.originalPosition = pos;
                    particle.position = pos;
                    particle.position.X += i;
                    particle.birthTime = (float)nowT.TotalGameTime.TotalMilliseconds;
                    particle.scaling = 1.0f;
                    particle.color = Color.BlueViolet;
                    particleList.Add(particle);
                }
                count++;
            }
            for (int i = 0; i < 50; i++)
            {
                particleList[i].position.X += velocity;
                if (particleList[i].position.X > (pos.X + length))
                    particleList[i].position = pos;
            }
            for (int i = particleList.Count - 1; i >= 0; i--)
            {
                spriteBatch.Draw(texture, particleList[i].position, null, particleList[i].color, i, new Vector2(16, 16), particleList[i].scaling, SpriteEffects.None, 1);
            }
        }
    }    
}
/* trailing algorithm goes like this:
spawn a new particle every deltaTime (specified in an argument)
spawn it at the new location wherever specified, and increase the radius as the distance gets further
 * if it goes up....rotate counterclockwise
 * if it goes down....rotate clockwise
*/